Option Explicit On
Option Strict On

Imports System.Collections
Imports System.Collections.Generic
Imports nstl
Imports NUnit.Framework
Imports NStl.Iterators.Support
Imports NStl.SyntaxHelper


Namespace nstl.test
    <TestFixture()> _
    Public Class uniqueset

        ''' <summary>
        ''' Initialize() is called once during test execution before
        ''' test methods in this test class are executed.
        ''' </summary>
        <SetUp()> Public Sub Initialize()
            ' TODO: Add test initialization code
        End Sub

        ''' <summary>
        ''' Cleanup() is called once during test execution after
        ''' test methods in this class have executed unless the
        ''' corresponding Initialize() call threw an exception.
        ''' </summary>
        <TearDown()> Public Sub Cleanup()
            ' TODO: Add test cleanup code
        End Sub
        <Test()> _
        Public Sub ReverseIterators()
            Dim m As New UniqueSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                m.Insert(i)
            Next

            Dim vb As New Vector(Of Integer)

            Algorithm.Copy(m.RBegin, m.REnd, NStlUtil.BackInserter(vb))

            TestUtil.equal(vb, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
        End Sub
        <Test()> _
        Public Sub insert()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            Assert.IsFalse(TestUtil.mismatch(Of Integer)(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))

            s = New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            Dim v As New Vector(Of Integer)
            For i As Integer = 9 To 0 Step -1
                v.PushBack(i)
            Next

            Algorithm.RandomShuffle(v.Begin, v.End)
            For i As Integer = 9 To 0 Step -1
                s.Insert(v(i))
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))


            s = New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Insert(s.Begin(), 0)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
            s.Insert(s.Begin(), 10)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))

        End Sub
        <Test()> _
        Public Sub erase_if()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))

            s.EraseIf(Bind.Second(Compare.Less(Of Integer)(), 6))
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {6, 7, 8, 9}))
        End Sub
        <Test()> _
        Public Sub clear()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))

            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Clear()
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {}))
            Assert.IsTrue(s.Empty())
        End Sub
        <Test()> _
        Public Sub count()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            Assert.IsTrue(s.CountOf(22) = 0)
            Assert.IsTrue(s.CountOf(2) = 1)
            Assert.IsFalse(s.CountOf(11) = 1)
        End Sub
        <Test()> _
        Public Sub empty()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            Assert.IsFalse(s.Empty())
            s.Clear()
            Assert.IsTrue(s.Empty())
        End Sub
        <Test()> _
        Public Sub equal_range()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)

            'set should contain 10, 20, 30

            Dim ret As Range(Of Integer, UniqueSet(Of Integer).Iterator) = s.EqualRange(20)
            Assert.IsTrue(DirectCast(ret.Begin().Value, Integer) = 20)
            Assert.IsTrue(DirectCast(ret.End().Value, Integer) = 30)
            Assert.IsTrue(Not ret.Begin().Equals(s.End()))

            ret = s.EqualRange(25)
            Assert.IsTrue(DirectCast(ret.Begin().Value, Integer) = 30)
            Assert.IsTrue(DirectCast(ret.End().Value, Integer) = 30)
            Assert.IsTrue(Not ret.Begin().Equals(s.End()))

            ret = s.EqualRange(40)
            Assert.AreEqual(ret.Begin(), s.End())
            Assert.AreEqual(ret.End(), s.End())
        End Sub
        <Test()> _
        Public Sub [erase]()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)

            'set should contain 10, 20, 30

            'erase at position
            Dim pos As UniqueSet(Of Integer).Iterator = NStlUtil.Advance(Of Integer, UniqueSet(Of Integer).Iterator)(s.Begin(), 1)
            Assert.IsTrue(DirectCast(pos.Value, Integer) = 20)
            s.Erase(pos)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 30}))

            'erase a range
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 20, 30, 40, 50}))
            '                                        0,  1,  2,  3,  4

            pos = NStlUtil.Advance(Of Integer, UniqueSet(Of Integer).Iterator)(s.Begin(), 1)
            Assert.IsTrue(DirectCast(pos.Value, Integer) = 20)
            Dim pos2 As UniqueSet(Of Integer).Iterator = NStlUtil.Advance(Of Integer, UniqueSet(Of Integer).Iterator)(s.Begin(), 3)
            Assert.AreEqual(pos2.Value, 40)
            s.Erase(pos, pos2)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 40, 50}))

            'erase a value
            Dim count As Integer = s.Erase(40)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 50}))
            Assert.AreEqual(count, 1)
            count = s.Erase(100)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 50}))
            Assert.AreEqual(count, 0)
        End Sub
        <Test()> _
        Public Sub find()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 20, 30, 40, 50}))

            Dim pos As UniqueSet(Of Integer).Iterator = s.Find(30)
            Assert.AreEqual(pos.Value, 30)
            Assert.AreEqual(NStlUtil.Distance(s.Begin(), pos), 2)
            Assert.AreNotEqual(pos, s.End())
            Assert.AreEqual(s.Find(42), s.End())
        End Sub
        <Test()> _
        Public Sub lower_upper_bound()
            'tested via find. Other tests are sensless with a set! All
            'that worth is allready tested with find
        End Sub
        <Test()> _
        Public Sub size()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            Assert.AreEqual(s.Count(), 0)
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '10, 20, 30, 40, 50
            Assert.AreEqual(s.Count(), 5)
        End Sub
        <Test()> _
        Public Sub swap()
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '10, 20, 30, 40, 50

            Dim s2 As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s2.Insert(80)
            s2.Insert(70)
            s2.Insert(60)
            s2.Insert(50)

            s.Swap(s2)

            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {50, 60, 70, 80}))
            Assert.IsFalse(TestUtil.mismatch(s2, New Integer() {10, 20, 30, 40, 50}))
        End Sub
        <Test()> _
        Public Sub customComparison()
            'Test the set with different comparison functors

            'less
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '10, 20, 30, 40, 50
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 20, 30, 40, 50}))

            'greater
            s = New UniqueSet(Of Integer)(Compare.Greater(Of Integer)())
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '50, 40, 30, 20, 10
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {50, 40, 30, 20, 10}))
        End Sub
        <Test()> _
        Public Sub TestIInsertableImp()
            Dim v As New Vector(Of Integer)()
            For i As Integer = 0 To 9
                v.PushBack(i)
            Next
            Algorithm.RandomShuffle(v.Begin, v.End)
            Dim s As New UniqueSet(Of Integer)(Compare.Less(Of Integer))
            Algorithm.Transform(v.Begin, v.End, NStlUtil.Inserter(s, s.Begin()), Project.Identity(Of Integer)())
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
        End Sub
    End Class
End Namespace

